package org.hzz.work.tree;

import org.hzz.common.utils.FastJsonUtil;
import org.hzz.work.tree.vo.Category;
import org.hzz.work.tree.vo.CategoryVo;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 将List转换为Tree
 * @author 胖卡
 * @version 1.0.0
 * @date 2024/7/13
 */
public class ListToTreeMain {
    public static void main(String[] args) {
        List<Category> data = getDataFromDb();
        String jsonStr = FastJsonUtil.toJSONStr(data);

        System.out.println(jsonStr);

        System.out.println("===============================");

        CategoryVo tree = toTree(data);
        // 因为返回的是伪父节点
        String treeJson = FastJsonUtil.toJSONStr(tree.getChildren());
        System.out.println(treeJson);

    }



    public static List<Category> getDataFromDb(){
        return List.of(
                new Category(2, 1, "Java开发"),
                new Category(1, 0, "IT.互联网"),
                new Category(3, 2, "SpringBoot"),
                new Category(4, 2, "MyBatis"),
                new Category(5, 0, "阅读"),
                new Category(6, 1, "前端开发")
        );
    }

    public static CategoryVo toTree(List<Category> categoryList){

        Map<Integer,CategoryVo> resultMap = new HashMap<>();

        for (Category category: categoryList){
            CategoryVo current = Converter.INSTANCE.toVo(category);
            current.setChildren(new ArrayList<>());

            // 处理这个节点的父节点
            Integer parentId = category.getParentId();
            CategoryVo parent = resultMap.get(parentId);
            if(parent == null){
                /*
                 * 此时还没map中还没有此节点的父节点
                 * 所以创建一个伪父节点，用来持有这个子节点
                 * 当处理到这个节点的父节点是，直接从这个伪父节点拿出children更新即可
                 * 最后放入更新的父节点到map中
                 */
                parent = new CategoryVo();
                parent.setChildren(new ArrayList<>());
            }
            // 将本次节点加入父节点
            parent.getChildren().add(current);

            // 处理这个节点的children,因为在处理到当前节点前它的子节点已经加入了容器。
            CategoryVo categoryVo = resultMap.get(current.getId());
            if(categoryVo != null){
                current.getChildren().addAll(categoryVo.getChildren());
            }

            resultMap.put(parentId,parent);
            // 本次节点可能也会成为其他节点的父节点，所以也要放入map
            resultMap.put(current.getId(),current);
        }
        return resultMap.get(0);
    }

    @Mapper
    public interface Converter{
        Converter INSTANCE = Mappers.getMapper(Converter.class);

        CategoryVo toVo(Category category);
    }

}
